#include "gtest/gtest.h"
#include "gx_hash.h"
#include "gx_err.h"
#include "gx_bsearch.h"
#include "gx_sort.h"
#include <limits.h>

#define TIMES 10000

TEST(hash_test,testinit)
{
	HASH *hash = hash_new(10000,0);
	ASSERT_NE(hash,(HASH*)NULL);
	hash_delete(hash,NULL,NULL);
}


TEST(hash_test,testadd)
{
	HASH *hash = hash_new(10000,0);
	ASSERT_NE(hash,(HASH*)NULL);

	for(int i=0;i<100;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		int* data = (int*)malloc(sizeof(int));
		*data = i;
		ASSERT_EQ(SUCCESS,hash_add(hash,keyword,data));
	}

	for(int i=0;i<100;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		int* data = (int*)malloc(sizeof(int));
		*data = i;
		ASSERT_EQ(DATA_EXIT,hash_add(hash,keyword,data));
		free(keyword);
		free(data);
	}
	hash_delete(hash,free,free);
}


TEST(hash_test,testfind)
{
	HASH *hash = hash_new(10000,0);
	ASSERT_NE(hash,(HASH*)NULL);

	for(int i=0;i<10000;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		int* data = (int*)malloc(sizeof(int));
		*data = i;
		ASSERT_EQ(SUCCESS,hash_add(hash,keyword,data));
	}

	for(int i=0;i<10000;i++)
	{
		char* keyword = (char*)malloc(100);
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		//printf("fuck:%s\n",keyword);
		ASSERT_EQ(i,*((int*)hash_find(hash,keyword)));
		//printf("i:%d\n",i);
		free(keyword);
	}

	for(int i=10000;i<100000;i++)
	{
		char* keyword = (char*)malloc(100);
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		//printf("fuck:%s\n",keyword);
		ASSERT_EQ(NULL,hash_find(hash,keyword));
		//printf("i:%d\n",i);
		free(keyword);
	}

	hash_delete(hash,free,free);
}


TEST(hash_test,testfind1)
{
	HASH *hash = hash_new(10000,sizeof(int));
	ASSERT_NE(hash,(HASH*)NULL);

	for(int i=0;i<10000;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		int* data = (int*)malloc(sizeof(int));
		*data = i;
		ASSERT_EQ(SUCCESS,hash_add(hash,data,keyword));
	}

	for(int i=0;i<10000;i++)
	{
		int* keyword = (int*)malloc(sizeof(int));
		ASSERT_NE(keyword,(int*)NULL);
		*keyword = i;
		char *data = (char*)malloc(100*sizeof(char));
		memset(data,0,100*sizeof(char));
		snprintf(data,100-1,"keyword%d",i);
		ASSERT_EQ(0,strcmp((char*)hash_find(hash,keyword),data));
		free(keyword);
		free(data);
	}

	for(int i=10000;i<100000;i++)
	{
		int *keyword = (int*)malloc(sizeof(int));
		ASSERT_NE(keyword,(int*)NULL);
		*keyword = i;
		ASSERT_EQ(NULL,hash_find(hash,keyword));
		free(keyword);
	}

	hash_delete(hash,free,free);
}

TEST(hash_test,testremove)
{
	HASH *hash = hash_new(10000,0);
	ASSERT_NE(hash,(HASH*)NULL);

	for(int i=0;i<10000;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		int* data = (int*)malloc(sizeof(int));
		*data = i;
		ASSERT_EQ(SUCCESS,hash_add(hash,keyword,data));
	}

	for(int i=0;i<5000;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		ASSERT_EQ(SUCCESS,hash_remove(hash,keyword,free,free));
		ASSERT_EQ(NULL,hash_find(hash,keyword));
		free(keyword);
	}

	for(int i=0;i<5000;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		ASSERT_EQ(NODATA,hash_remove(hash,keyword,free,free));
		free(keyword);
	}
	hash_delete(hash,free,free);
}


TEST(hash_test,testremove1)
{
	HASH *hash = hash_new(10000,sizeof(int));
	ASSERT_NE(hash,(HASH*)NULL);

	for(int i=0;i<10000;i++)
	{
		int *data =(int *)malloc(sizeof(int));
		*data = i;
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		ASSERT_EQ(SUCCESS,hash_add(hash,data,keyword));
	}

	for(int i=0;i<5000;i++)
	{
		int *data =(int *)malloc(sizeof(int));
		*data = i;
		ASSERT_NE(data,(int*)NULL);
		ASSERT_EQ(SUCCESS,hash_remove(hash,data,free,free));
		ASSERT_EQ(NULL,hash_find(hash,data));
		free(data);
	}

	for(int i=0;i<5000;i++)
	{
		int *data =(int *)malloc(sizeof(int));
		*data = i;
		ASSERT_NE(data,(int*)NULL);
		ASSERT_EQ(NODATA,hash_remove(hash,(void*)&i,NULL,free));
		free(data);
	}

	hash_delete(hash,free,free);
}

TEST(hash_test,testtravel)
{
	HASH *hash1 = hash_new(10000,0);
	ASSERT_NE(hash1,(HASH*)NULL);
	HASH *hash2 = hash_new(10000,0);
	ASSERT_NE(hash2,(HASH*)NULL);

	for(int i=0;i<10000;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		int* data = (int*)malloc(sizeof(int));
		*data = i;
		ASSERT_EQ(SUCCESS,hash_add(hash1,keyword,data));
	}

	for(int i=0;i<10000;i++)
	{
		char* keyword = (char*)malloc(100*sizeof(char));
		ASSERT_NE(keyword,(char*)NULL);
		memset(keyword,0,100);
		snprintf(keyword,100-1,"keyword%d",i);
		int* data = (int*)malloc(sizeof(int));
		*data = i;
		ASSERT_EQ(SUCCESS,hash_add(hash2,keyword,data));
	}

	HASH_NODE * node = hash_findfirst(hash1);
	ASSERT_NE(node,(HASH_NODE*)NULL);

	while(node != NULL)
	{
		ASSERT_NE((void*)NULL,hash_find(hash2,node->key));
		ASSERT_EQ(SUCCESS,hash_remove(hash2,node->key,free,free));
		node = hash_findnext(hash1);
	}
	ASSERT_EQ((unsigned)0,hash2->count);
	hash_delete(hash1,free,free);
	hash_delete(hash2,free,free);
}

/*
TEST(bsearchtest,simple)
{
	
	int a[10] = {0,1,2,3,4,5,6,7,8,9};

	for(int i=0;i<10;i++)
	{
		ASSERT_EQ(i,*(bsearch(i,a,10)));
	}

	for(int i=10;i<20;i++)
	{
		ASSERT_EQ(NULL,bsearch(i,a,10));
	}
	

	int b[5] = {1,3,5,7,9};

	for(int i=0;i<10;i++)
	{
		if(i%2==0)
			ASSERT_EQ(NULL,bsearch(i,b,5));
		else
			ASSERT_EQ(i,*(bsearch(i,b,5)));
	}
}
*/

int compare(const void* d1,const void* d2)
{
	int a = *(int*)d1;
	int b = *(int*)d2;
	return a-b;
}

/*
TEST(bsearchtest,rand)
{
	srand(time(NULL));
	for(int i=0;i<100;i++)
	{
		SET* set = set_new(10000,sizeof(int));
		int *array=NULL;
		int row = rand()%100;

		
		array = (int*)malloc(row*sizeof(int));

		for(int j=0;j<row;j++)
		{
			int * key = (int*)malloc(sizeof(int));
			*key = rand()%100;
			array[j] = *key;
			if(set_add(set,key) != SUCCESS)
			{
				free(key);
			}
		}
		

		
		qqsort((void*)array,row,sizeof(int),compare);

		for(int k=0;k<100;k++)
		{
			int* key = (int*)malloc(sizeof(int));
			ASSERT_NE((int*)NULL,key);
			*key = rand()%100;

			if(set_find(set,key) == 1)
			{
				ASSERT_NE((int*)NULL,bsearch(*key,array,row));
			}
			else
			{
				ASSERT_EQ((int*)NULL,bsearch(*key,array,row));
			}
			free(key);
		}
		
		set_delete(set,free);
		free(array);
	}
}
*/

TEST(testset,set)
{
	SET* set = set_new(10000,sizeof(int));
	set_delete(set,NULL);
}


TEST(testset,setadd)
{
	SET* set = set_new(10000,sizeof(int));
	//set_delete(set,NULL);

	for(int i =0;i<100000;i++)
	{
		int *key = (int*)malloc(sizeof(int));
		ASSERT_NE((int*)NULL,key);
		*key = i;
		ASSERT_EQ(SUCCESS,set_add(set,key));
	}
	

	for(int i=0;i<100000;i++)
	{
		int *key = (int*)malloc(sizeof(int));
		ASSERT_NE((int*)NULL,key);
		*key = i;
		ASSERT_EQ(1,set_find(set,key));
		free(key);
	}

	for(int i=0;i<100000;i++)
	{
		int *key = (int*)malloc(sizeof(int));
		ASSERT_NE((int*)NULL,key);
		*key = i;
		ASSERT_EQ(SUCCESS,set_remove(set,key,free));
		free(key);
	}
	
	set_delete(set,free);
}


TEST(bsearchtest,testvoid)
{
	int a[10] = {0,1,2,3,4,5,6,7,8,9};

	for(int i=0;i<10;i++)
	{
		ASSERT_EQ(i,*(int*)(bsearch(&i,a,10,sizeof(int),compare)));
	}

	for(int i=10;i<20;i++)
	{
		ASSERT_EQ(NULL,bsearch(&i,a,10,sizeof(int),compare));
	}


	int b[5] = {1,3,5,7,9};

	for(int i=0;i<10;i++)
	{
		if(i%2==0)
			ASSERT_EQ(NULL,bsearch(&i,b,5,sizeof(int),compare));
		else
			ASSERT_EQ(i,*(int*)(bsearch(&i,b,5,sizeof(int),compare)));
	}

}

TEST(bsearchtest,voidrand)
{
	srand(time(NULL));
	for(int i=0;i<100;i++)
	{
		SET* set = set_new(10000,sizeof(int));
		int *array=NULL;
		int row = rand()%100;

		
		array = (int*)malloc(row*sizeof(int));

		for(int j=0;j<row;j++)
		{
			int * key = (int*)malloc(sizeof(int));
			*key = rand()%100;
			array[j] = *key;
			if(set_add(set,key) != SUCCESS)
			{
				free(key);
			}
		}
		

		qqsort((void*)array,row,sizeof(int),compare);

		for(int k=0;k<100;k++)
		{
			int* key = (int*)malloc(sizeof(int));
			ASSERT_NE((int*)NULL,key);
			*key = rand()%100;

			if(set_find(set,key) == 1)
			{
				ASSERT_NE((void*)NULL,bsearch(key,array,row,sizeof(int),compare));
			}
			else
			{
				ASSERT_EQ((void*)NULL,bsearch(key,array,row,sizeof(int),compare));
			}
			free(key);
		}
		
		set_delete(set,free);
		free(array);
	}
}
